home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / communic / pcmail / main / gphys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  6.9 KB  |  246 lines

  1. /*++
  2. /* NAME
  3. /*    gphys 3
  4. /* SUMMARY
  5. /*    g protocol packet input/output
  6. /* PROJECT
  7. /*    pc-mail
  8. /* PACKAGE
  9. /*    cico
  10. /* SYNOPSIS
  11. /*    #include "gp.h"
  12. /*
  13. /*    void gsctrl(fd,c)
  14. /*    int fd,c;
  15. /*
  16. /*    void gsdata(fd,pk,c)
  17. /*    int fd,c;
  18. /*    Packet *pk;
  19. /*
  20. /*    int grpack(fd,pk)
  21. /*    int fd;
  22. /*    Packet *pk;
  23. /* DESCRIPTION
  24. /*    The functions in this module send and receive packets. Interfacing
  25. /*    is based on Packet structures. Messages are interpreted elsewhere.
  26. /*
  27. /*    gsctrl() sends a control packet to the remote receiver (no data
  28. /*    segment).
  29. /*
  30. /*    gsdata() sends a data packet to the remote receiver. 
  31. /*    The Packet structure is completed with a 16-bit checksum.
  32. /*    This function expects read/write sequence information in 
  33. /*    the c parameter.
  34. /*
  35. /*    grpack() receives a packet from the remote transmitter and checks
  36. /*    its integrity. It fills in the k, c, len and check fields of the 
  37. /*    Packet structure and returns the type of message (DATA, SHORT, 
  38. /*    CLOSE, RJ, RR, etcetera).
  39. /* DIAGNOSTICS
  40. /*    grpack() returns FAIL if a corrupted packet was received, and
  41. /*    TIME if no packet was received within the time-out interval.
  42. /* BUGS
  43. /*    No data re-reading in case of transmission errors.
  44. /*    Some parts of the code rely on 8-bit bytes, 16-bit short integers.
  45. /* AUTHOR(S)
  46. /*    W.Z. Venema
  47. /*    Eindhoven University of Technology
  48. /*    Department of Mathematics and Computer Science
  49. /*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  50. /* CREATION DATE
  51. /*    Sun Apr 19 11:39:27 GMT+1:00 1987
  52. /* LAST MODIFICATION
  53. /*    90/01/22 13:01:42
  54. /* VERSION/RELEASE
  55. /*    2.1
  56. /*--*/
  57.  
  58. #include <signal.h>
  59. #include <setjmp.h>
  60. #include "gp.h"
  61.  
  62. /* local and forward declarations */
  63.  
  64. static jmp_buf timebuf;
  65. static int chksum(),readhead(),readdata(),clkint();
  66.  
  67. #define    READ(fd,cp,n)    { if (read(fd,cp,n) != n) clkint(); }
  68.  
  69. /*
  70. * "A six byte framing envelope is constructed using the control"
  71. * "byte C of a packet and five other bytes as depicted below."
  72. *        <DLE><k><c0><c1><C><x>
  73. * "The <DLE> symbol denotes the ASCII ctrl/P character. If the"
  74. * "envelope is to be followed by a data segment, <k> has the"
  75. * "value log2(size)-4; i.e. 1 <= k < 8. If k is 9, then the"
  76. * "envelope represents a control packet. The <c0> and <c1>"
  77. * "bytes are the low-order and high-order bytes respectively of"
  78. * "0xAAA minus a 16-bit checksum. For control packets, this"
  79. * "16-bit checksum is the same as the control byte C. For data"
  80. * "packets, the checksum is calculated by the program below."
  81. * "The <x> byte is the exclusive-or of <k><c0><c1><C>. Error"
  82. * "control is accomplished by checking a received framing"
  83. * "envelope for compliance with the definition, and comparing a"
  84. * "checksum function of the data segment with <c0><c1>."
  85. */
  86.  
  87. /* gsctrl - send control packet (no data segment) */
  88.  
  89. void gsctrl(fd,c)
  90. int fd,c;
  91. {
  92.     char header[6];
  93.     register char chkhdr;
  94.     register char *cp = header;
  95.     int cksm = MAGIC-c;                /* do checksum */
  96.  
  97.     *cp++ = CTRL('P');                /* start of header */
  98.     chkhdr  = *cp++ = KCTRL;            /* k byte (control) */
  99.     chkhdr ^= *cp++ = cksm;            /* c0 byte (checksum lsb) */
  100.     chkhdr ^= *cp++ = cksm>>8;            /* c1 byte (checksum msb) */
  101.     chkhdr ^= *cp++ = c;            /* message|sequence info */
  102.     *cp = chkhdr;                /* header checksum */
  103.  
  104.     write(fd,header,sizeof(header));        /* send header */
  105.     DEBUG(9,"xmt: %o\n",c&0377);        /* show header */
  106. }
  107.  
  108. /* gsdata - send data packet */
  109.  
  110. void gsdata(fd,pk,c)
  111. int fd,c;
  112. register Packet *pk;
  113. {
  114.     char header[6];
  115.     register char chkhdr;
  116.     register char *cp = header;
  117.     int cval = pk->c|(c&077);            /* fold in sequence info */
  118.  
  119.     pk->chk = MAGIC-(chksum(pk->data,pk->len)^(0377&cval));
  120.  
  121.     *cp++ = CTRL('P');                /* start of header */
  122.     chkhdr  = *cp++ = pk->k;            /* k byte (message length) */
  123.     chkhdr ^= *cp++ = pk->chk;            /* c0 byte (checksum lsb) */
  124.     chkhdr ^= *cp++ = pk->chk>>8;        /* c1 byte (checksum msb) */
  125.     chkhdr ^= *cp++ = cval;            /* data|sequence info */
  126.     *cp = chkhdr;                /* header checksum */
  127.  
  128.     write(fd,header,sizeof(header));        /* send header */
  129.     DEBUG(9,"xmt: %o\n",cval&0377);        /* show header */
  130.  
  131.     write(fd,pk->data,pk->len);            /* send data segment */
  132.     DEBUG(9,"xmt: data %d bytes\n",pk->segl);    /* show data */
  133. }
  134.  
  135. /* grpack - receive one data or control packet; return packet type info */
  136.  
  137. int grpack(fd,pk)
  138. int fd;
  139. register Packet *pk;
  140. {
  141.     if (setjmp(timebuf))            /* in case we time out */
  142.     return(TIME);                /* it just happened */
  143.     signal(SIGALRM,clkint);            /* alarm clock response */
  144.     alarm(ALARM);                /* set alarm clock */
  145.  
  146.     if (readhead(fd,pk)) {            /* read packet header */
  147.     DEBUG(7,"rcv: bad header\n","");
  148.     alarm(0);                /* turn timer off */
  149.     return(FAIL);                /* header checksum error */
  150.     } else if (pk->k == KCTRL) {
  151.     alarm(0);                /* turn timer off */
  152.     return(MESG(pk->c));            /* CLOSE | RJ | RR etcetera */
  153.     } else if (readdata(fd,pk)) {
  154.     DEBUG(7,"rcv: bad data\n","");
  155.     alarm(0);                /* turn timer off */
  156.     return(FAIL);                /* data checksum error */
  157.     } else {
  158.     alarm(0);                /* turn timer off */
  159.     return(TYPE(pk->c));            /* DATA | SHORT */
  160.     }
  161. }
  162.  
  163. /* readhead - read header and check header checksum */
  164.  
  165. static int readhead(fd,pk)
  166. int fd;
  167. register Packet *pk;
  168. {
  169.     char header[5];
  170.     int ok;
  171.     register char chkhdr;
  172.     register char *cp = header;
  173.  
  174.     do {                    /* start reading */
  175.     READ(fd,cp,1);                /* skip all garbage */
  176.     } while (*cp != CTRL('P'));            /* up to packet header */
  177.  
  178.     READ(fd,header,sizeof(header));        /* read packet header */
  179.  
  180.     chkhdr  = pk->k = *cp++;            /* data length or control */
  181.     chkhdr ^= pk->chk = *cp++&0377;        /* data checksum lsb */
  182.     chkhdr ^= *cp;
  183.     pk->chk |= (*cp++&0377)<<8;    /* data checksum msb */
  184.     chkhdr ^= pk->c = *cp++;            /* control packet or data */
  185.     if (ok = (chkhdr == *cp))
  186.     DEBUG(9,"rcv: %o\n",pk->c&0377);
  187.     return(!ok);                /* check the checksum */
  188. }
  189.  
  190. /* readdata - read data segment and check data checksum */
  191.  
  192. static int readdata(fd,pk)
  193. int fd;
  194. register Packet *pk;
  195. {
  196.     if (seglen[pk->k] > pk->len) {
  197.     DEBUG(7,"rcv: data %d bytes too big\n",seglen[pk->k]);
  198.     return(1);
  199.     } else {
  200.     register int i;
  201.     DEBUG(9,"rcv: data %d bytes\n",pk->len = seglen[pk->k]);
  202.     for (i = 0; i < pk->len; i++) {
  203.         READ(fd,&pk->data[i],1);
  204.     }
  205.     return(pk->chk+(chksum(pk->data,pk->len)^(pk->c&0377)) != MAGIC);
  206.     }
  207. }
  208.  
  209. /* clkint - tiny time-out routine */
  210.  
  211. static int clkint()
  212. {
  213.     DEBUG(9,"rcv: timed out\n","");
  214.     longjmp(timebuf,1);
  215.     /* NOTREACHED */
  216. }
  217.  
  218. /* chksum - unix packet driver checksum algorithm */
  219.  
  220. static int chksum(s,n)
  221. register char *s;
  222. register n;
  223. {
  224.     register short sum;
  225.     register unsigned short t;
  226.     register short x;
  227.  
  228.     sum = -1;
  229.     x = 0;
  230.     do {
  231.     if (sum < 0) {
  232.         sum <<= 1;
  233.         sum++;
  234.     } else
  235.         sum <<= 1;
  236.     t = sum;
  237.     sum += (unsigned)*s++ & 0377;
  238.     x += sum ^ n;
  239.     if ((unsigned short)sum <= t) {
  240.         sum ^= x;
  241.     }
  242.     } while (--n > 0);
  243.  
  244.     return(sum);
  245. }
  246.